package com.tengju.bff.interfaces.manage.member.article.facade;

import com.google.common.collect.Lists;
import com.tengju.bff.interfaces.app.announcement.assembler.AnnounceArticleAssembler;
import com.tengju.bff.interfaces.app.announcement.vo.AnnounceArticleVO;
import com.tengju.bff.interfaces.app.announcement.vo.AnnounceVO;
import com.tengju.bff.interfaces.app.announcement.vo.PageAnnounceArticleVO;
import com.tengju.bff.interfaces.manage.member.article.vo.ArticleContextVO;
import com.tengju.bff.interfaces.manage.member.article.vo.GetArticleForm;
import com.tengju.bff.interfaces.shared.*;
import com.tengju.data.domain.shared.CastUtil;
import com.tengju.support.application.article.ArticleService;
import com.tengju.support.domain.model.alert.AlertEvent;
import com.tengju.support.domain.model.alert.AlertService;
import com.tengju.support.domain.model.article.Article;
import com.tengju.support.domain.model.article.ArticleId;
import com.tengju.support.domain.model.article.ArticleRepository;
import com.tengju.support.domain.model.article.ArticleType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ArticleFacade {

    @Value("${app.compliance.announce.prefix.url}")
    private String prefixURL;

    @Resource
    private ArticleRepository articleRepository;

    @Resource
    private ArticleService articleService;

    @Resource
    private AlertService alertService;

    final ExecutorService threadPool = Executors.newSingleThreadExecutor();

    public TableVO getArticleByPage(GetArticleForm form) {
        TableVO tableVO = new TableVO();
        tableVO.setHeader(List.of(
                ColumnVO.of("articleId", "文章ID", false),
                ColumnVO.of("title", "文章标题", false),
                ColumnVO.of("createTime", "创建时间", false),
                ColumnVO.of("viewCnt", "浏览量", false),
                ColumnVO.of("type", "类型", false),
                ColumnVO.of("createBy", "添加人", false)
        ));
        Integer pageSize = form.getPageSize();
        Integer pageIndex = form.getPageIndex();
        int offset = (pageIndex - 1) * pageSize;

        ArticleId articleId = Optional.ofNullable(form.getArticleId())
                .map(ArticleId::new)
                .orElse(null);

        int total = articleRepository.count(articleId,
                form.getTitle(), ArticleType.fromVal(form.getType()));

        if (offset > total) {
            return null;
        }
        List<Article> articles = articleRepository.queryByPage(articleId,
                form.getTitle(), ArticleType.fromVal(form.getType()), offset, pageSize);

        List<Map<String, Object>> records = new ArrayList<>();
        for (Article articleRow : articles) {
            Map<String, Object> row = new HashMap<>();
            row.put("articleId", articleRow.getArticleId().getValue());
            row.put("title", articleRow.getTitle());
            row.put("createTime", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(articleRow.getCreateTime()));
            row.put("viewCnt", articleRow.getViewCnt());
            row.put("type", articleRow.getArticleType().getDesc());
            row.put("createBy", articleRow.getCreateBy());
            row.put("context", articleRow.getContext());
            records.add(row);
        }
        tableVO.setRecords(records);
        tableVO.setPage(PageResultVO.of(pageIndex, pageSize, total));
        return tableVO;
    }

    public ArticleContextVO getArticleContext(ArticleId articleId) throws InterfaceException {
        Article article = articleRepository.get(articleId);
        if (article == null) {
            throw new InterfaceException(InterfaceCode.ARTICLE_NOT_EXIST);
        }
        threadPool.submit(() -> {
            try {
                articleService.updateArticleViewCnt(articleId);
            } catch (Exception e) {
                AlertEvent event = new AlertEvent("文章浏览量更新异常");
                event.addItem("articleId", articleId.getValue());
                alertService.alert(event);
            }
        });
        return new ArticleContextVO(article.getTitle(), article.getContext());
    }

    public PageAnnounceArticleVO getAnnounceArticleByPage(GetArticleForm form) {
        PageAnnounceArticleVO pageAnnounceArticleVO = new PageAnnounceArticleVO();
        Integer pageSize = form.getPageSize();
        Integer pageIndex = form.getPageIndex();
        int offset = Math.max((pageIndex - 1) * pageSize,0);

        pageAnnounceArticleVO.setPageIndex(pageIndex);
        pageAnnounceArticleVO.setPageSize(pageSize);

        ArticleId articleId = Optional.ofNullable(form.getArticleId())
                .map(ArticleId::new)
                .orElse(null);
        List<AnnounceArticleVO> announceArticleVOS = Lists.newArrayList();
        List<Article> articles = articleRepository.queryByPage(articleId,
                form.getTitle(), ArticleType.fromVal(form.getType()), offset, pageSize);
        if (CollectionUtils.isEmpty(articles)) {
            pageAnnounceArticleVO.setAnnounceArticleList(announceArticleVOS);
            return pageAnnounceArticleVO;
        }
        announceArticleVOS =  articles.stream()
                .map(v -> AnnounceArticleAssembler.modelToVO(v,prefixURL))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        pageAnnounceArticleVO.setAnnounceArticleList(announceArticleVOS);
        return pageAnnounceArticleVO;

    }

    public List<AnnounceVO> getAnnounceType() {
        List<AnnounceVO> announceVOList = List.of(
                new AnnounceVO(ArticleType.COMPLIANCE_NOTICE.getVal(), ArticleType.COMPLIANCE_NOTICE.getDesc()),
                new AnnounceVO(ArticleType.VIOLATION_NOTICE.getVal(), ArticleType.VIOLATION_NOTICE.getDesc())

        );
        return announceVOList;
    }

}
